dojo.provide("apt.CalendarDay");
dojo.require("apt.DataRow");
dojo.require("dijit._WidgetBase");
dojo.require("dijit._TemplatedMixin");
dojo.require("dijit.WidgetSet");

dojo.declare("apt.CalendarDay", [dijit._WidgetBase, dijit._TemplatedMixin], {
    templateString: dojo.cache('apt.templates', 'CalendarDay.html'),
    widgetsInTemplate: true,

    date: "",
    formattedDate: "",
    minHourElementWidth: 18, // Pixels
    baseClass: "day",
    dayStart: 6,
    dayEnd: 20,
    hours: "",
    pixelTime: "",
    week: "",
    cache: "",
    brain: "", //reference to PlanningTool Widget,
    resources: "",
    status: "",
    isShowing: false,
    isHidden: false,
    width: 100,

    constructor: function (data) {
        this.inherited(arguments);
        dojo.safeMixin(this, data);

        this.status = {availabilityLoaded: false, reservationsLoaded: false};
        this.resources = {};

        this.dataRows = new dijit.WidgetSet();

        if (Object.prototype.toString.call(this.date) != "[object Date]") {
            console.error('Invalid Date object passed to CalendarDay');
            this.date = new Date();
        }

        this.baseClass = (this.date.toISOString().substr(0, 10) == this.brain.today.toISOString().substr(0, 10)) ? 'day today' : 'day';

        this.formattedDate = this.date.getDayName().substr(0, 2) + " " + this.date.getDate() + "." + (this.date.getMonth() + 1) + ".";

        if (this.date.getDay() == 1) {
            this.week = "Week " + this.date.getWeek();
        }

        this.cache = {pixelsPerHour: -1};
    },

    postCreate: function () {
    },

    startup: function () {
        if (this.isShowing) {
            this.queryAvailabilitiesAndReservations();
        }
        this.resize();
    },
    
    reload: function () {
        var self = this;
        if (self.readyReload && self.isShowing && self.dataRowsNode) {
            //console.log('reload fired!');
            self.dataRowsNode.interceptors = {};
            dojo.empty(self.dataRowsNode);
            self.queryAvailabilitiesAndReservations();
            //self.resize();
        }

    },

    delete: function () {
        dojo.style(this.domNode, 'display', 'none');
        for (var key in this.resources) {
            if (this.resources.hasOwnProperty(key)) {
                this.brain.removeResource(key);
            }
        }
        ;
        this.destroyRecursive();
    },

    isStillShowing: function () {
        // TODO: This errors out sometimes with ok consequenses;
        if (this.parent.domNode && this.domNode) {
            var pos = dojo.position(this.parent.domNode);
            var left = pos.x;
            var right = pos.x + pos.w;
            var epos = dojo.position(this.domNode);
            return (epos.x < right && epos.x + epos.w > left);
        } else {
            return false;
        }
    },

    setShowing: function () {
        this.isHidden = false;
        if (!this.isShowing) {
            this.isShowing = true;
            setTimeout(dojo.hitch(this, function () {
                    if (this.isStillShowing()) {
                        this.startup();
                    } else {
                        this.isShowing = false;
                    }
                })
                , 600); //500
        }
        ;
    },

    setIsHidden: function () {
        this.isShowing = false;
        this.isHidden = true;
        // this.dataRows.forEach(function(w, i){ w.destroyRecursive(); });
    },

    queryAvailabilitiesAndReservations: function () {
        var dayEnd = this.dayEndAsDate().toISOString().substr(0, 10);
        var dayStart = this.dayStartAsDate().toISOString().substr(0, 10);
        //debugger;
        //dayStart = '2014-09-09';
        // service/calendar.aspx?type=days&startDate=2012-06-22&endDate=2012-06-22
        var filterObj = dojo.queryToObject(window.location.search.replace("?", ""));
        var queryStr = dojo.mixin(filterObj, {
            startDate: dayStart,
            endDate: dayEnd
        });
        dojo.when(
            this.brain.stores.availabilities.query(queryStr),
            dojo.hitch(this, function (result) {
                this.availabilityLoaded(result)
            }),
            dojo.hitch(this, function (result) {
                this.availabilityLoadError(error)
            })
        );

        dojo.when(
            this.brain.stores.reservations.query(queryStr),
            dojo.hitch(this, function (result) {
                this.reservationsLoaded(result)
                //console.log(result)
            }),
            dojo.hitch(this, function (result) {
                this.reservationsLoadError(error)
            })
        );

    },

    availabilityLoadError: function (error) {
        console.log('Could not load availabilities for day', error);
    },

    reservationsLoadError: function (error) {
        console.log('Could not load reservations for day', error);
    },

    availabilityLoaded: function (result) {
        if (result.length > 0) {
            //debugger;
            //console.log('availabilityLoaded > 0');
            var self = this;
            result.forEach(function (e, i) {
                if (!self.resources.hasOwnProperty(e.SmanId)) {
                    self.brain.addResource(e.SmanId);
                }
                self.resources[e.SmanId] = self.resources[e.SmanId] || {};
                if (!self.resources[e.SmanId].hasOwnProperty('availabilities')) self.resources[e.SmanId].availabilities = [];
                if (!self.resources[e.SmanId].hasOwnProperty('breaks')) self.resources[e.SmanId].breaks = [];

                if (e.Type == self.brain.variables.break) {
                    self.resources[e.SmanId].breaks = self.resources[e.SmanId].breaks || [];
                    self.resources[e.SmanId].breaks.push(e);
                } else if (e.Type == self.brain.variables.work) {
                    self.resources[e.SmanId].availabilities = self.resources[e.SmanId].availabilities || [];
                    self.resources[e.SmanId].availabilities.push(e);
                }

            });
        }
        this.status.availabilityLoaded = true;
        if (this.status.reservationsLoaded) {
            this.renderDay();
        }
    },

    reservationsLoaded: function (result) {
        //debugger;
        if (result.length > 0) {
            var self = this;
            //self.date = new Date(2014, 8, 9, 12, 0, 0, 0);  // set to test ---> need to delete
            var dayEnd = new Date(this.date);
            dayEnd.setDate(this.date.getDate() + 1);

            result.forEach(function (reservation, i) {
                dojo.forEach(reservation.Resources, function (resx, ri) {
                    //console.log("Date: ", self.date, resx.StartTime, resx.EndTime);
                    var startTime = Date.parse(resx.StartTime);
                    var endTime = Date.parse(resx.EndTime);
                    if (endTime >= self.date && startTime < dayEnd) {
                        if (!self.resources.hasOwnProperty(resx.ResourceId)) {
                            self.brain.addResource(resx.ResourceId);
                        }
                        var newReservation = {};
                        newReservation.SmanId = resx.ResourceId;
                        newReservation.StartTimeJSDate = startTime; //resx.StartTime.parseISO8601();
                        newReservation.EndTimeJSDate = endTime;     //resx.EndTime.parseISO8601();
                        newReservation.ReservationNumber = reservation.ReservationNumber;
                        newReservation.ReservationInfo = resx.ReservationInfo || reservation;

                        // newReservation.Root = e;
                        self.resources[resx.ResourceId] = self.resources[resx.ResourceId] || {};
                        self.resources[resx.ResourceId].reservations = self.resources[resx.ResourceId].reservations || [];
                        self.resources[resx.ResourceId].reservations.push(newReservation);
                    }
                });
            });
            // console.log('reservationsLoaded', result);      
        }
        this.status.reservationsLoaded = true;
        if (this.status.availabilityLoaded) {
            this.renderDay();
        }
    },

    renderDay: function () {
        var self = this;
        var resources = this.brain.resources || {};
        if (this.brain.filterByResourceId && this.brain.filterByResourceId  != 0) {
            resources = [{
                SmanId: this.brain.filterByResourceId,
                count: 1
            }];
        }
        dojo.forEach(resources, function (e, i) {
            self.dataRowsNode.interceptors = self.dataRowsNode.interceptors || {};
            // Fix repeated days
            if (!self.dataRowsNode.interceptors[e.SmanId]) {
                var dataForResource = {};
                // console.log(e.SmanId, t.resources[e.SmanId]);
                if (self.resources.hasOwnProperty(e.SmanId) && self.resources[e.SmanId].hasOwnProperty('availabilities') && self.resources[e.SmanId].availabilities.length > 0) {
                    dataForResource = self.resources[e.SmanId];
                }
                var row = new apt.DataRow({resourceName: e.SmanId, parent: self, data: dataForResource});
                self.dataRows.add(row);
                self.dataRowsNode.interceptors[e.SmanId] = e.SmanId;
                row.placeAt(self.dataRowsNode);
                //debugger;
            }
        })
        // autoReload
        self.readyReload = true;
    },

    dayLength: function () {
        var len = this.dayEnd - this.dayStart;
        if (len < 1) {
            throw "Day length shouldn't be smaller than 1 hour";
        }
        return len;
    },

    // createDataRowsForResources: function(){
    //     // Luo datarowt this.resources objectin order propertyn mukaisessa järjestyksessä;
    //
    //   for (var i=0; i <  this.brain.calendarData.resources.length; i++) {
    //     var row = (new apt.DataRow( { resourceName: this.brain.calendarData.resources[i], parent: this } ));
    //     this.dataRows.add(row);
    //     row.placeAt(this.dataRowsNode);
    //   };
    // },

    resize: function (viewPortSize) {
        this.resetPixelsPerHour();
        this.daysShowing = this.parent.daysShowing;

        if (typeof viewPortSize == 'undefined') {
            viewPortSize = dojo.position(this.parent.domNode).w;
        }

        var daySize = parseInt(viewPortSize / this.parent.daysShowing);
        dojo.style(this.domNode, 'width', daySize + "px");

        if (this.isShowing) {
            this.createHourElements();
            this.dataRows.forEach(function (dataRow) {
                //debugger;
                dataRow.resize();
            });
        }
    },

    // updateHourElements: function(){
    //   var hourElementLength = (dojo.position(this.domNode).w -1) / this.hours.length <<0;
    //   dojo.map(this.hours, function(hour){
    //     dojo.style(hour, 'width', hourElementLength + "px");
    //   });
    // },

    createHourElements: function () {
        this.hourArea.innerHTML = '';
        this.hours = [];

        // Count maximum number of hour indicator elements that can be fitted to the widget
        var maxElements = dojo.position(this.domNode).w / this.minHourElementWidth;
        maxElements = maxElements | maxElements // Same as Math.floor() twice as fast;
        if (maxElements > this.dayLength()) {
            maxElements = this.dayLength();
        }

        // Integer for how many hours long one hour indicator element must be
        var hourElementTimeSpan = Math.ceil(this.dayLength() / maxElements);

        // var elementWidth =
        for (var i = this.dayStart; i < this.dayEnd; i = i + hourElementTimeSpan) {
            var hour = dojo.create("td", {innerHTML: '<div class="hour" style="margin: auto; width: 18px; text-align: center;">' + i + '</div>'});
            this.hours.push(hour);
            dojo.place(hour, this.hourArea);
        }
        ;

        // var hourElementLength = (dojo.position(this.domNode).w -2) / this.hours.length <<0;
        // dojo.map(this.hours, function(hour){
        //   dojo.style(hour, 'width', hourElementLength + "px");
        // });

        // dojo.style(this.domNode, 'width', hourElementLength * this.hours.length + 2 + "px");
    },

    getDataRowStartAndEnd: function (start, end) {
        if (this.dayEnd < end) {
            this.dayEnd = end;
        }
        if (this.dayStart > start) {
            this.dayStart = start;
        }
    },

    dayEndAsDate: function () {
        this.cache.dayEndAsDate = this.cache.dayEndAsDate || new Date(this.date.getFullYear(), this.date.getMonth(), this.date.getDate(), this.dayEnd);

        return this.cache.dayEndAsDate;
    },

    dayStartAsDate: function () {
        this.cache.dayStartAsDate = this.cache.dayStartAsDate || new Date(this.date.getFullYear(), this.date.getMonth(), this.date.getDate(), this.dayStart);

        return this.cache.dayStartAsDate;
    },

    extractEventsForDay: function (item) {
        return (item.StartTime.toDateFromAspNet() < this.dayEndAsDate() && item.EndTime.toDateFromAspNet() > this.dayStartAsDate());
    },

    extractAvailabilityForDay: function (item) {
        var day = item.WorkingDay.toDateFromAspNet();
        return (item.Type == "Work" && day.getYear() == this.dayStartAsDate().getYear() && day.getMonth() == this.dayStartAsDate().getMonth() && day.getDate() == this.dayStartAsDate().getDate() );
    },

    extractBreaksForDay: function (item) {
        var day = item.WorkingDay.toDateFromAspNet();
        return (item.Type == "Break" && day.getYear() == this.dayStartAsDate().getYear() && day.getMonth() == this.dayStartAsDate().getMonth() && day.getDate() == this.dayStartAsDate().getDate() );
    },

    getLeftOffsetForTime: function (hours, minutes) {
        var h = hours + (minutes / 60) - this.dayStart;
        var px = this.getPixelsForHour(h);
        return px;
    },

    getRightOffsetForTime: function (hours, minutes) {
        var h = this.dayEnd - (hours + (minutes / 60));
        var px = this.getPixelsForHour(h);
        return px;
    },

    resetPixelsPerHour: function () {
        this.cache.pixelsPerHour = -1;
    },

    getPixelsForHour: function (hours) {
        var pixelsPerHour = this.cache.pixelsPerHour;
        if (pixelsPerHour === -1) {
            var pixels = dojo.position(this.domNode).w;
            pixelsPerHour = pixels / this.dayLength();
            this.cache.pixelsPerHour = pixelsPerHour;
        }
        return pixelsPerHour * hours;
    }


});